// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.api.ads.dfa.matchtables;

import com.google.api.ads.dfa.axis.v1_20.ApiException;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;

/**
 * Encapsulates all non-page-able SOAP request and retry logic
 *
 * @author Moshe Kahan
 */
class SoapLookup<Record> extends AbstractSoapLookup<Record> {

  private static Random randomGenerator = new Random();

  private SoapLookupCallback<Record> soapLookupCallback;

  /**
   * Construct SoapLookup without any input entity IDs.
   */
  SoapLookup(SoapLookupCallback<Record> soapLookupCallback) {
    super();
    this.soapLookupCallback = soapLookupCallback;
  }

  /**
   * Construct SoapLookup with collection of input entity ID Longs.
   */
  SoapLookup(Collection<Long> entityIdCollection, SoapLookupCallback<Record> soapLookupCallback) {
    super(entityIdCollection);
    this.soapLookupCallback = soapLookupCallback;
  }

  /**
   * Perform a non-paginated SOAP lookup on this sub-set of IDs.
   *
   * @param ids set of IDs to retrieve entities for.
   */
  @Override
  void executeRequest(long[] ids) throws DfaRemoteException {
    clearRecordArray();
    List<Record> subRecordArray = new ArrayList<Record>();
    boolean success = false;
    int attempts = 0;
    do {
      try {
        ++attempts;
        soapLookupCallback.getRecords(ids, subRecordArray);
        success = true;
      } catch (ApiException e) {
        System.err.println("SOAP ERROR! Attempt #" + attempts + " with exception: " + e);
        e.printStackTrace(System.err);
        if (attempts > 2) {
          System.err.println("Received APIException from DFA SOAP API event after 3 attempts."
              + " Skipping...");
          break;
        }
      } catch (RemoteException e) {
        System.err.println("SOAP ERROR! Attempt #" + attempts + " with exception: " + e);
        e.printStackTrace(System.err);
        if (attempts > 2) {
          throw new DfaRemoteException(
              "Received RemoteException from DFA SOAP API event after 3 attempts", e);
        }
      }
      try {
        if (!success) {
          // Sleep for 1 to 5 seconds.
          Thread.sleep(randomGenerator.nextInt(5) * 1000 + 1000);
        }
      } catch (InterruptedException e) {
        e.printStackTrace(System.err);
        Thread.currentThread().interrupt();
        throw new DfaRemoteException("Received interrupt", e);
      }
    } while (!success);
    addRecords(subRecordArray);
    resetRecordArrayIterator();
  }
}
